package cn.itsource.service.impl;


import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import cn.itsource.constants.Constants;
import cn.itsource.exception.GlobalException;
import cn.itsource.pojo.api.AddLogin;
import cn.itsource.pojo.app.dto.AppRegisterDto;
import cn.itsource.pojo.app.vo.GeoVo;
import cn.itsource.pojo.domain.Driver;
import cn.itsource.mapper.DriverMapper;
import cn.itsource.result.R;
import cn.itsource.romate.api.LoginApi;
import cn.itsource.service.IDriverService;
import cn.itsource.service.IDriverSettingService;
import cn.itsource.service.IDriverSummaryService;
import cn.itsource.service.IDriverWalletService;
import cn.itsource.template.WechatTemplate;
import cn.itsource.utils.BitStatesUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.util.Date;


/**
 * <p>
 * 司机对象 服务实现类
 * </p>
 *
 * @author beishan
 * @since 2024-03-25
 */
@Service
@Slf4j
public class DriverServiceImpl extends ServiceImpl<DriverMapper, Driver> implements IDriverService {

    @Autowired
    private IDriverSettingService settingService;

    @Autowired
    private IDriverSummaryService summaryService;

    @Autowired
    private IDriverWalletService walletService;

    @Autowired
    private LoginApi loginApi;

    @Autowired
    private WechatTemplate wechatTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 保存司机实时位置到redis
     * @param vo
     */
    @Override
    public void geo(GeoVo vo) {
        Point point = new Point(Double.parseDouble(String.valueOf(vo.getLongitude())),Double.parseDouble(String.valueOf(vo.getLatitude())) );
        redisTemplate.opsForGeo().add(Constants.Redis.DRIVER_LOCATION_KEY,point,StpUtil.getLoginIdAsLong());
    }

    @Override
    @GlobalTransactional(name = "driver-wechat-register",rollbackFor = Exception.class)
    public void register(AppRegisterDto appRegisterDto) {
        //获取微信的openid
        String openid = wechatTemplate.getOpenid(appRegisterDto.getWxCode());
        String phone = wechatTemplate.getPhone(appRegisterDto.getPhoneCode());
        //通过openid 查询数据库
        Driver driver = super.getOne(new LambdaQueryWrapper<Driver>().eq(Driver::getOpenId, openid));
        //判断 司机是否为空 不为空说明已经注册了 为空则说明没有注册
        if (driver != null) {
            throw new GlobalException("该账号已注册");
        }

        //使用雪花算法生成 id
        Long id = IdUtil.createSnowflake(1, 1).nextId();
        //为空 则将司机信息添加到 数据库
        addDriver(openid,id,phone);

        //将司机id 设置到相关联的表
        //司机配置表
        settingService.creatDriver(id);

        //司机结算表
        summaryService.creatDriver(id);

        //司机钱包表
        walletService.creatDriver(id);

        //远程 添加login
        addDriverToLogin(id,openid,phone);

    }



    /**
     * 添加 司机的登录信息
     * @param id 司机id
     * @param openid 司机微信的openid
     * @param phone 司机手机号
     */
    public void addDriverToLogin(Long id, String openid,String phone){
        AddLogin addLogin = new AddLogin();
        addLogin.setId(id);
        addLogin.setUsername(phone);
        addLogin.setType(1);
        addLogin.setOpenId(openid);
        addLogin.setPhone(phone);

        R r = loginApi.addLogin(addLogin);
        if (!r.isSuccess()) {
            throw new GlobalException("注册失败");
        }
    }

    /**
     * 添加司机
     * @param openId 司机微信的openid
     * @param id 司机id
     * @param phone 司机手机号
     * @return
     */
    public Driver addDriver(String openId,Long id,String phone ){
        Driver driver = new Driver();
        driver.setOpenId(openId);
        driver.setId(id);
        driver.setPhone(phone);
        driver.setCreateTime(new Date());
        //位状态
        long state = BitStatesUtil.addState(0L, BitStatesUtil.OP_PHONE);
        driver.setBitState(state);
        super.save(driver);
        return driver;
    }
}
